package com.sunsy.authserver.exception;

import com.sunsy.authserver.beans.R;
import com.sunsy.authserver.enums.EApiErrorCode;
import com.sunsy.authserver.enums.IApiErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.sunsy.authserver.enums.EApiErrorCode.VALIDATE_EXC;

/**
 * @author 孙思远
 * @date 2021/7/19
 */
@RestControllerAdvice
@Slf4j
public class SdhGlobalExceptionAdvice {

  /**
   * apiException异常处理返回
   */
  @ExceptionHandler(ApiException.class)
  public R apiException(ApiException ae) {
    IApiErrorCode aec = Optional.ofNullable(ae.getErrorCode()).orElse(EApiErrorCode.FAILED);
    return R.failed(aec, ae.getMessage());
  }

  /**
   * 方法校验异常
   */
  @ExceptionHandler(value = MethodArgumentNotValidException.class)
  public R exceptionHandler(MethodArgumentNotValidException e) {
    String msg = null;
    if (e.getBindingResult() != null && !CollectionUtils
        .isEmpty(e.getBindingResult().getAllErrors())) {
      msg = e.getBindingResult().getAllErrors().stream().filter(Objects::nonNull)
          .map(DefaultMessageSourceResolvable::getDefaultMessage).collect(
              Collectors.joining(", "));
    } else {
      msg = e.getMessage();
    }
    return R.failed(VALIDATE_EXC, msg);
  }

  /**
   * 绑定校验异常
   */
  @ExceptionHandler(value = BindException.class)
  public R validationExceptionHandler(BindException e) {
    e.printStackTrace();
    return R.failed(VALIDATE_EXC, "参数绑定异常");
  }

  /**
   * bean校验异常
   */
  @ExceptionHandler(value = ConstraintViolationException.class)
  public R ConstraintViolationExceptionHandler(ConstraintViolationException ex) {
    String msg = ex.getConstraintViolations().stream().filter(Objects::nonNull)
        .map(cv -> cv == null ? "null" : cv.getPropertyPath() + ": " + cv.getMessage())
        .collect(Collectors.joining(", "));
    return R.failed(VALIDATE_EXC, msg);
  }

  /**
   * 其他异常处理返回
   */
  @ExceptionHandler(Exception.class)
  public R exception(Exception e) {
    log.error("global exception:{}", e);
    return R.failed(EApiErrorCode.FAILED);
  }

}
